<?php
/**
 * 彩票服务程序，开奖数据的获取，生成分析图，推送到客户端
 * Created by PhpStorm.
 * User: zzx
 * Date: 2017/10/28
 * Time: 下午2:19
 */


include 'config.php'; // 参数配置
include 'func.php'; // 函数
$redis = redis_con();
$prev = $config['REDIS_PREFIX'] . 'datas_'; // redis前缀
$analyz = generate(); // 实例一个单双分析器
$analyz_kl8 = generate_kl8(); // 实例一个单双分析器

class Config {
	public static $prev = 'cpiao_datas_';
	// 时时彩当期信息
	public static $u_current_ssc = 'http://caipiao.163.com/order/preBet_periodInfoTime.html?gameEn=ssc&cache=1509008328582';
	public static $u_current_kl8 = 'http://chart.cp.360.cn/int/qcurissue?LotID=265108';
	
	// 获取近期开奖信息
	public static $u_recent_ssc = 'http://caipiao.163.com/award/getAwardNumberInfo.html?gameEn=ssc&cache=1509008420470&periodNum=20';
	public static $u_recent_kl8 = 'http://chart.cp.360.cn/zst/qkj/?lotId=265108';
	
	// 查询某一期的信息
	public static $u_last_ssc = 'http://caipiao.163.com/award/getAwardNumberInfo.html?gameEn=ssc&cache=1509009076076&period=';
	public static $u_last_kl8 = 'http://chart.cp.360.cn/zst/qkj/?lotId=265108';
	
	public static function getSscCurrent(&$serv){
		try {
			$redis = redis_con();
			$current = $redis->hGetAll(Config::$prev . 'current');
			//如果仍然是当前期，直接反回
			if(isset($current['ssc_openTime']) && $current['ssc_openTime'] != '' && $current['ssc_openTime'] > 0 && $current['ssc_openTime'] > time()){
				return false;
			}
			
			echo "\n获取当期信息ssc……\n";
			
    		$ssc_current = curl(Config::$u_current_ssc, 8000, true);
// 	    	print_r(json_decode($ssc_current, true));
	    	$ssc_current = json_decode($ssc_current, true);
	    	
    		if (isset($ssc_current['status']) && $ssc_current['status'] == 0) {
    			$r_ssc_current = $redis->hGetAll(Config::$prev . 'ssc_current');
	    		if(isset($r_ssc_current['period'])){
	    			if($r_ssc_current['period'] != $ssc_current['currentPeriod']){
	    				$redis->hmSet(Config::$prev . 'ssc_wait', [
	                        'currentPeriod' => $ssc_current['currentPeriod'],
	                        'opentime' => time() + round($ssc_current['secondsLeft'] / 1000),
	                    ]);
	    				
	    				$redis->hSet(Config::$prev . 'current', 'ssc', $ssc_current['currentPeriod']); // 更新当期编号
	                    $redis->hSet(Config::$prev . 'current', 'ssc_openTime', round($ssc_current['secondsLeft'] / 1000) + time()); // 清除开奖时间
	    				
	    				//start task to get last win info
	    				$serv->task([
	    						'type'=>'get_ssc_win',
	    						'data'=>[
	    								'period'=>$r_ssc_current['period']
	    						],
	    				]);
	    				
	    				//update current hash
	    				$redis->hMset(Config::$prev . 'ssc_current', [
			    				'period'=>$ssc_current['currentPeriod'],
	    						'left'=>round($ssc_current['secondsLeft'] / 1000),
			    		]);
	    			}
	    		}else{
	    			$redis->hmSet(Config::$prev . 'ssc_wait', [
                        'currentPeriod' => $ssc_current['currentPeriod'],
                        'opentime' => time() + round($ssc_current['secondsLeft'] / 1000),
                    ]);
	    			
					$redis->hSet ( Config::$prev . 'current', 'ssc', $ssc_current['currentPeriod'] ); // 更新当期编号
					$redis->hSet(Config::$prev . 'current', 'ssc_openTime', round($ssc_current['secondsLeft'] / 1000) + time()); // 清除开奖时间
	    			
		    		$redis->hMset(Config::$prev . 'ssc_current', [
		    				'period'=>$ssc_current['currentPeriod'],
		    				'left'=>round($ssc_current['secondsLeft'] / 1000),
		    		]);
	    		}
    		}//end if res status
    	}catch(Exception $e){
    		echo $e->getMessage();
    	}
    	
    	unset($redis); 
    	unset($ssc_current);
    	unset($r_ssc_current);
	}
	
	public static function getKl8Current(&$serv){
		try {
			$redis = redis_con();
			$current = $redis->hGetAll(Config::$prev . 'current');
			//如果仍然是当前期，直接反回
			if(isset($current['kl8_openTime']) && $current['kl8_openTime'] != '' && $current['kl8_openTime'] > 0 && $current['kl8_openTime'] > time()){
				return false;
			}
			
			echo "\n获取当期信息…k18…\n";
	        $res = curl(Config::$u_current_kl8, 500);
	        $res = json_decode($res, true);
			
	        if(isset($res['IsOpen']) && $res['IsOpen'] == '0'){
				$redis->hSet ( Config::$prev . 'current', 'kl8', $res ['Issue'] ); // 更新当期编号 todo 有下期编号吗？应该在结束下单后，立即更新当期编号为下一期
				// 订单处理平仓时间，在开奖时间上，再加若干秒，视情况调整
// 				$redis->hSet ( Config::$prev . 'current', 'kl8_openTime', strtotime ( $res ['BonusTime'] ) ); // 设置开奖时间
				$redis->hSet ( Config::$prev . 'current', 'kl8_openTime', strtotime ( $res ['OpenTime'] ) ); // 设置开奖时间
	        }
	        
	        $r_kl8_current = $redis->hGetAll(Config::$prev . 'kl8_current');
    		if(isset($r_kl8_current['period'])){
    			if($r_kl8_current['period'] != $res['Issue']){
    				
    				$redis->hmSet(Config::$prev . 'kl8_wait', [
                        'currentPeriod' => $res['Issue'],
                        'opentime' => $res['EndTime'],
                    ]);
    				
//     				//start task to get last win info
//     				$serv->task([
//     						'type'=>'get_kl8_win',
//     						'data'=>[
//     								'period'=>$r_kl8_current['period']-1
//     						],
//     				]);
    				
    				$redis->hMset(Config::$prev . 'kl8_current', [
		    				'period'=>$res['Issue'],
    						'left'=>$res['EndTime'],
		    		]);
    			}
    		}else{
    			$redis->hmSet(Config::$prev . 'kl8_wait', [
                        'currentPeriod' => $res['Issue'],
                        'opentime' => $res['EndTime'],
                    ]);
	    		$redis->hMset(Config::$prev . 'kl8_current', [
	    				'period'=>$res['Issue'],
	    				'left'=>$res['EndTime'],
	    		]);
    		}
    	}catch(Exception $e){
    		echo $e->getMessage();
    	}
    	
    	unset($redis);
    	unset($time);
    	unset($res);
    	unset($r_kl8_current);
	}
	
	public static function getSscResult($period, $retry = 0){
		global $analyz;
		if($retry == 20){
			return false;
		}
		
		echo "获取当期开奖…ssc…\n";
        $re = curl(Config::$u_last_ssc . $period, 8000, true);
        $re = json_decode($re, true);
        if(isset($re['status']) && $re['status'] == 0){
        	//set redis cache and update k line
        	$redis = redis_con();
        	
        	$re = $re['awardNumberInfoList'][0];
        	$v = [];
        	$v[0] = $re['period'];
            $v[1] = $re['winningNumber'];
            
        	// 保存到缓存中，供订单处理平仓
			$redis->hSet ( Config::$prev . 'current', 'ssc_openeriod', $v [0] ); // 开奖期号
			$redis->hSet ( Config::$prev . 'current', 'ssc_winningNumber', $v [1] ); // 开奖结果
			                                                             
			// 写入存储队列
			$redis->lPush ( Config::$prev . 'win_queue', json_encode ( [ 
					$v [0],
					$v [1] 
			] ) );
			$redis->lPush ( Config::$prev . 'win_oqueue', json_encode ( [ 
					'type' => 'ssc',
					'data' => [ 
							$v [0],
							$v [1] 
					] 
			] ) );
			
			// 开奖结果写入缓存
			$redis->setex(Config::$prev . 'winresult' . $v[0], 3600 * 24 * 30, $v[1]);
			
			// 读取缓存中的最近一期P
			$t = $redis->lGetRange ( Config::$prev . 'ssc', 0, 0 );
			if ($t) {
				$t = json_decode ( $t [0], true );
			}
			// 对比缓存期数
			if (! $t || $t [0] != $v [0]) {
				// 加入缓存list
				echo json_encode ( $v ) . "\n";
				$redis->lPush ( Config::$prev . 'ssc', json_encode ( $v ) );
				
				// 删除过多的缓存数据
				if ($redis->lSize ( Config::$prev . 'ssc' ) > 120) {
					$redis->rPop ( Config::$prev . 'ssc' );
				}
				
				echo "当期获取成功：{$re['period']}\n";
				
				// 分析趋势
				$analyz->send ( [ 
						'period' => $v [0],
						'num' => $v [1] 
				] ); // 分析
				$re = $analyz->current (); // 获取分析结果
				$analyz->next (); // 前进
				up_cache ( $re ); // 更新分析结果的缓存
				
				sleep(1);
				
				unset($re);
				unset($t);
				unset($v);
				
				return true;
			}else{
				sleep(1);
				unset($re);
				unset($t);
				unset($v);
				return false;
			}
        	
        }else{
        	sleep(15);
	        unset($re);
        	Config::getSscResult($period, $retry + 1);
        }
	}
	
	public static function getKl8Result(){
		global $analyz_kl8;
		if($retry == 30){
			return false;
		}
		
		echo "获取当期开奖kl8……" . "\n";
        $re = curl(Config::$u_last_kl8, 5000);
        $re = json_decode($re, true);
        
        $v = [];
        $v[0] = $re[0]['Issue']; // 上期开奖期号
        $v[1] = $re[0]['WinNumber']; // 上期开奖结果
        $v[2] = $re['preEndTime']; // 上期开奖时间
//         if(isset($re['now']) && $re['preIssue'] == $re[0]['Issue']){

        //set redis cache and update k line
        $redis = redis_con();
        $period = $redis->get(Config::$prev . 'lastkl8_period');
        if((empty($period) && isset($re['now'])) || (!empty($period) && isset($re['now']) && $period != $re[0]['Issue'])){
        	
        	$redis->set(Config::$prev . 'lastkl8_period', $re[0]['Issue']);
        	
        // 保存到缓存中，供订单处理平仓
            $redis->hSet(Config::$prev . 'current', 'kl8_Issue', $v[0]); // 开奖期号
            $redis->hSet(Config::$prev . 'current', 'kl8_WinNumber', $v[1]); // 开奖结果
            //$redis->hSet($prev . 'current', 'kl8_openTime', $v[2]); // 设置开奖时间
            
            //写入存储队列
            $redis->lPush(Config::$prev . 'win_queue', json_encode([$v[0], $v[1]]));
            $redis->lPush(Config::$prev . 'win_oqueue', json_encode([
                'type'=>'kl8',
                'data'=>[$v[0], $v[1]]
            ]));
            
            //开奖结果写入缓存
            $redis->setex(Config::$prev . 'winresult' . $v[0], 3600 * 24 * 30, $v[1]);
            
            //now
            $send_k = false;
            if($redis->exists(Config::$prev . 'kl8') && $redis->lSize(Config::$prev . 'kl8') >= 1){
                $last_issue = $redis->lrange(Config::$prev . 'kl8', 0, 0);
                $last_issue = json_decode($last_issue[0], true);
                
                if($last_issue[0] != $re[0]['Issue']){
                    // 加入缓存list
                    $redis->lPush(Config::$prev . 'kl8', json_encode($v));
                    $send_k = true;
                }
                unset($last_issue);
            }else{
                // 加入缓存list
                $redis->lPush(Config::$prev . 'kl8', json_encode($v));
                $send_k = true;
            }
            
            //删除过多的缓存数据
            if($redis->lSize(Config::$prev . 'kl8') > 120){
                $redis->rPop(Config::$prev . 'kl8');
            }
            
            if($send_k){
				$analyz_kl8->send ( [ 
						'period' => $v [0],
						'num' => $v [1],
						'open_time' => $re ['preEndTime'] 
				] ); // 分析
				$rek = $analyz_kl8->current (); // 获取分析结果
				
				$analyz_kl8->next (); // 前进
				up_cache_kl8($rek); // 更新分析结果的缓存
				
				sleep(1);
				
// 				unset($analyz_kl8);
            }
            
            sleep(1);
            
            unset($re);
            unset($send_k);
            unset($redis);
            unset($v);
            
		}
	}
}

// $analyz = generate(); // 实例一个单双分析器
// $analyz_kl8 = generate_kl8(); // 实例一个单双分析器
$server = new swoole_websocket_server("0.0.0.0", 9915);

$server->set(array(
    'daemonize' => 0, // 守护进程
//    'worker_num' => 2, // 工作进程数量，本地虚拟机环境使用，测试和生产环境注意修改
   'task_worker_num' => 64, // 异步任务进程数量
    'pid_file' => __DIR__ . '/serv.php.pid', // server进程PID
));


// Config::getSscResult('171231021');

/**
 * 
 * ssc_last
 * ssc_current
 * 
 */
$server->on('WorkerStart', function ($serv, $worker_id) {
//    echo "WorkerStart{$worker_id}\n";
    swoole_timer_tick(10000, function () use ($serv, $worker_id) {
	    if ($worker_id == 0) {
	    	Config::getSscCurrent($serv);
	    }
	    
	    if ($worker_id == 1) {
			Config::getKl8Current($serv);
	    }
    });
    
    swoole_timer_tick(30000, function () use ($serv, $worker_id) {
	    if ($worker_id == 1) {
			Config::getKl8Result();
	    }
    });
    
});

$server->on('Request', function ($request, $response) {

});

$server->on('Task', function ($server, $task_id, $from_id, $data) {
	switch ($data['type']) {
		case 'get_ssc_win':
			echo 'get_ssc_win';
			$period = $data['data']['period'];
			Config::getSscResult($period);
			break;
			
		default:
			break;
	}
});

$server->on('open', function (swoole_websocket_server $server, $request) {

});

$server->on('Finish', function ($server, $task_id, $data) {

});

$server->on('message', function (swoole_websocket_server $server, $frame) {

});

$server->on('close', function ($ser, $fd) {

});

$server->start();

